package network;

import repeat.UdpDatagramServer;

import java.io.IOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.SocketException;

/**
 * Created with IntelliJ IDEA.
 * Description:
 * User: Hua YY
 * Date: 2024-10-07
 * Time: 17:20
 */
public class UdpEchoServer {
    //1：创建DatagramSocket对象
    private DatagramSocket socket = null;//socket:插槽插座
    //2：构造方法，服务器一启动，就要关联/绑定上一个操作系统中的端口号（服务器的端口号哦啊通常由程序员指定）
    //抛出的异常通常为scoket创建失败
    public UdpEchoServer(int port) throws SocketException {
        socket = new DatagramSocket(port);//端口号port
    }
    //3：服务器启动逻辑
    //5：抛异常，网络编程socket本质上也是IO
    public void start() throws IOException {
        System.out.println("服务器启动");
        while(true){
            //3：创建一个数据报包，它是每次发送数据和接收数据的一个基本单位
            // 参数为输出型参数，字节数组，对应UDP的载荷部分(传输层 )，一开始是空的
            DatagramPacket requestPacket = new DatagramPacket(new byte[4096],4096);
            //4；socket读网卡能读到一个UDP数据报（里面会包含数据源IP，源端口），放到requestPacket（数据报）对象中
            //如果没有接受到请求那么就会阻塞等待，此处收到的数据是先存到socket文件的内存缓冲区中。非硬盘
            socket.receive(requestPacket);
            //5：基于字节数组构造String对象，数组中的数据可能是文本数据（给String刚好）也可能是二进制数据（Java也能保存）
            //这里的长度是有效长度
            String request = new String(requestPacket.getData(),0,requestPacket.getLength());
            //6：根据请求计算响应
            String response = process(request);
            //7:把响应（String）字节给拎出来，构造成一个DatagramPacket数据报,在传入socket对象（因为4中我们说过收到请求时，socket能读到源IP和源端口）
            //这时我们把这个源IP和源端口，作为响应的目的IP和目的端口（确认客户端的发出请求的位置），返回回去
            //注：response.length()单位是字符，此处单位是字节
            DatagramPacket responsePacket = new DatagramPacket(response.getBytes() , response.getBytes().length , requestPacket.getSocketAddress());
            socket.send(responsePacket);
            //打印日志
            System.out.printf("[%s:%d] req: %s , resp: %s\n" , requestPacket.getAddress().toString(),
                    requestPacket.getPort(), request,response);
        }
    }
    //7：构造响应，这里是回显服务器，所以就是单纯的return
    private String process(String request) {
        return request;
    }

    public static void main(String[] args) throws IOException {
        UdpDatagramServer server = new UdpDatagramServer(9090);//端口号范围（1024，65535）
        server.start();
    }


}
